package com.example.ui;

import com.alibaba.csp.sentinel.util.AssertUtil;
import com.example.config.MQConsumeConfig;
import com.example.model.Result;
import com.example.service.MsgService;
import com.example.service.SecKillService;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping(path = "/seckill")
public class SeckillController {


    private static int corePoolSize = Runtime.getRuntime().availableProcessors();
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
            corePoolSize + 5,
            10l,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1000));

    @Autowired
    SecKillService secKillService;

    @Autowired
    MsgService msgService;
    private final Logger LOGGER = LoggerFactory.getLogger(SeckillController.class);
    /**
     * 使用AOP + 锁
     * @param seckillId
     * @param buyUserNum
     */
    @RequestMapping(path = "/buyshoppingByAop.do")
    public void buyshoppingByAop(long seckillId, Integer buyUserNum) {
        secKillService.deleteRecord();
        CountDownLatch countDownLatch = new CountDownLatch(buyUserNum);
        LOGGER.info("开始购买");
        for (int i = 0; i < buyUserNum; i++) {
            Runnable task = () -> {
                Random random = new Random();
                Long userId = random.nextLong();
                Result result = secKillService.buyShoppingByAOP(seckillId, userId);
                if(null != result) {
                    LOGGER.info("用户:{}{}", userId, result.get("msg"));
                }
                countDownLatch.countDown();
            };
            threadPoolExecutor.submit(task);
        }
    }

    /**
     * 悲观锁
     * @param seckillId
     * @param buyUserNum
     */
    @RequestMapping(path = "/buyshoppingByDataBaseForUpDate.do")
    public void buyshoppingByDataBaseForUpDate(long seckillId, Integer buyUserNum) {

        secKillService.deleteRecord();
        CountDownLatch countDownLatch = new CountDownLatch(buyUserNum);
        LOGGER.info("开始购买");
        for (int i = 0; i < buyUserNum; i++) {
            Runnable task = () -> {
                Random random = new Random();
                Long userId = random.nextLong();
                Result result = secKillService.buyShoppingForUpdate(seckillId, userId);
                if(null != result) {
                    LOGGER.info("用户:{}{}", userId, result.get("msg"));
                }
                countDownLatch.countDown();
            };
            threadPoolExecutor.submit(task);
        }
    }

    @RequestMapping(path = "/buyshoppingByhappyLock.do")
    public void buyshoppingByhappyLock(long seckillId, Integer buyUserNum) {

        secKillService.deleteRecord();
        CountDownLatch countDownLatch = new CountDownLatch(buyUserNum);
        LOGGER.info("开始购买");
        for (int i = 0; i < buyUserNum; i++) {
            Runnable task = () -> {
                Random random = new Random();
                Long userId = random.nextLong();
                Result result = secKillService.buyShoppingForHapiness(seckillId, userId);
                if(null != result) {
                    LOGGER.info("用户:{}{}", userId, result.get("msg"));
                }
                countDownLatch.countDown();
            };
            threadPoolExecutor.submit(task);
        }
    }
}
